package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.constant.GlobalConstant;
import com.csun.cmny.base.dto.LoginAuthDto;
import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.UacActionMapper;
import com.csun.cmny.provider.dao.UacRoleActionMapper;
import com.csun.cmny.provider.model.domain.UacAction;
import com.csun.cmny.provider.model.domain.UacMenu;
import com.csun.cmny.provider.model.domain.UacRoleAction;
import com.csun.cmny.provider.model.dto.action.ActionMainQueryDto;
import com.csun.cmny.provider.model.dto.action.UacActionCheckCodeDto;
import com.csun.cmny.provider.model.dto.action.UacActionCheckUrlDto;
import com.csun.cmny.provider.model.dto.menu.UacMenuCheckCodeDto;
import com.csun.cmny.provider.model.enums.UacActionStatusEnum;
import com.csun.cmny.provider.model.exceptions.UacBizException;
import com.csun.cmny.provider.model.vo.ActionVo;
import com.csun.cmny.provider.model.vo.MenuVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.UacActionService;
import com.csun.cmny.provider.service.UacMenuService;
import com.csun.cmny.util.PublicUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.AntPathMatcher;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

/**
 * The class Uac action service.
 *
 * @author paascloud.net@gmail.com
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UacActionServiceImpl extends BaseService<UacAction> implements UacActionService {

    @Resource
    private UacMenuService uacMenuService;
	@Resource
	private CmnyMessageSource cmnyMessageSource;
	@Resource
	private UacActionMapper uacActionMapper;
	@Resource
	private UacRoleActionMapper uacRoleActionMapper;
	private AntPathMatcher antPathMatcher = new AntPathMatcher();

	@Override
	@Transactional(readOnly = true, rollbackFor = Exception.class)
	public PageInfo queryActionListWithPage(ActionMainQueryDto actionMainQueryDto) {
		List<Long> menuIdList = actionMainQueryDto.getMenuIdList();
		Long menuId = null;
		if (PublicUtil.isNotEmpty(menuIdList)) {
			menuId = menuIdList.get(menuIdList.size() - 1);
		}
		UacAction uacAction = new UacAction();
		uacAction.setMenuId(menuId);
		BeanUtils.copyProperties(actionMainQueryDto, uacAction);
		uacAction.setOrderBy("update_time desc");
		PageHelper.startPage(actionMainQueryDto.getPageNum(), actionMainQueryDto.getPageSize());
		List<ActionVo> actionList = uacActionMapper.queryActionListWithPage(uacAction);
		return new PageInfo<>(actionList);
	}

	@Override
	public int deleteActionById(Long actionId) {
		//查询该角色下是否有用户绑定, 有的话提醒不能删除
		if (null == actionId) {
			throw new IllegalArgumentException("权限ID不能为空");
		}

		UacAction uacAction = uacActionMapper.selectByPrimaryKey(actionId);
		if (uacAction == null) {
			logger.error("找不到权限信息 actionId={}", actionId);
			throw new UacBizException(ErrorCodeEnum.UAC10014001, actionId);
		}

		// 删除角色权限表数据  不查询了 直接删除了
		// uacRoleActionMapper.deleteByActionId(actionId);

        // 校验功能是否分配到角色功能表
        UacRoleAction uacRoleAction = new UacRoleAction();
        uacRoleAction.setActionId(actionId);
        int count = uacRoleActionMapper.selectCount(uacRoleAction);
        if (count > 0) {
            throw new UacBizException(ErrorCodeEnum.UAC10014005);
        }

		return uacActionMapper.deleteByPrimaryKey(actionId);
	}

	@Override
	public void batchDeleteByIdList(List<Long> deleteIdList) {
		logger.info("批量删除角色. deleteIdList={}", deleteIdList);
		Preconditions.checkArgument(PublicUtil.isNotEmpty(deleteIdList), "删除权限ID不能为空");
		int result = uacActionMapper.batchDeleteByIdList(deleteIdList);
		if (result < deleteIdList.size()) {
			throw new UacBizException(ErrorCodeEnum.UAC10014002, Joiner.on(GlobalConstant.Symbol.COMMA).join(deleteIdList));
		}
	}

	@Override
	public int saveAction(UacAction action, LoginAuthDto loginAuthDto) {

		// 校验功能名
		Preconditions.checkArgument(PublicUtil.isNotEmpty(action.getActionName()),
				cmnyMessageSource.getMessage("action.name.null", null));

		// 校验功能编码
        Preconditions.checkArgument(PublicUtil.isNotEmpty(action.getActionCode()),
                cmnyMessageSource.getMessage("action.code.null", null));

        // 校验功能编码是否唯一
        UacActionCheckCodeDto uacActionCheckCodeDto = new UacActionCheckCodeDto();
        uacActionCheckCodeDto.setActionCode(action.getActionCode());
        Preconditions.checkArgument(checkActionCode(uacActionCheckCodeDto),
                cmnyMessageSource.getMessage("action.code.exist", null));

        // 校验功能URL
        Preconditions.checkArgument(PublicUtil.isNotEmpty(action.getUrl()),
                cmnyMessageSource.getMessage("action.url.null", null));

        // 校验功能URL是否唯一
        UacActionCheckUrlDto uacActionCheckUrlDto = new UacActionCheckUrlDto();
        uacActionCheckUrlDto.setUrl(action.getUrl());
        Preconditions.checkArgument(checkActionUrl(uacActionCheckUrlDto),
                cmnyMessageSource.getMessage("action.url.exist", null));

        if (PublicUtil.isNotEmpty(action.getMenuId())) {
            // 校验菜单是否存在
            UacMenu uacMenu = uacMenuService.selectByKey(action.getMenuId());
            if (PublicUtil.isEmpty(uacMenu)) {
                throw new UacBizException(ErrorCodeEnum.UAC10013003);
            }
        }

        action.setStatus(UacActionStatusEnum.ENABLE.getType());
		action.setUpdateInfo(loginAuthDto);

		return uacActionMapper.insertSelective(action);
	}

	@Override
	public int deleteByMenuId(Long id) {
		Preconditions.checkArgument(id != null, "菜单ID不能为空");

		return uacActionMapper.deleteByMenuId(id);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Exception.class)
	public List<Long> getCheckedActionList(Long roleId) {
		if (roleId == null) {
			throw new UacBizException(ErrorCodeEnum.UAC10012001);
		}
		return uacActionMapper.getCheckedActionList(roleId);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Exception.class)
	public List<MenuVo> getOwnAuthList(Long userId) {
		return uacActionMapper.getOwnAuthList(userId);
	}

	@Override
	@Transactional(readOnly = true, rollbackFor = Exception.class)
	public List<Long> getCheckedMenuList(Long roleId) {
		if (roleId == null) {
			throw new UacBizException(ErrorCodeEnum.UAC10012001);
		}
		return uacActionMapper.getCheckedMenuList(roleId);
	}

	@Override
	public List<UacAction> getOwnActionListByUserId(Long userId) {
		if (userId == null) {
			throw new UacBizException(ErrorCodeEnum.UAC10011001);
		}
		List<UacAction> uacActionList;
		if (Objects.equals(userId, GlobalConstant.Sys.SUPER_MANAGER_USER_ID)) {
			// 获取全部权限信息
			uacActionList = uacActionMapper.selectAll();
		} else {
			uacActionList = uacActionMapper.getOwnUacActionListByUserId(userId);
		}
		return uacActionList;
	}

	@Override
	public List<UacAction> listActionListByRoleId(Long roleId) {
		return uacActionMapper.listActionListByRoleId(roleId);
	}

	@Override
	public List<UacAction> listActionList(List<UacMenu> uacMenus) {
		return uacActionMapper.listActionList(uacMenus);
	}

	@Override
	public UacAction matchesByUrl(String requestUrl) {
		List<UacAction> uacActionList = uacActionMapper.selectAll();
		for (UacAction uacAction : uacActionList) {
			String url = uacAction.getUrl();
			if (StringUtils.isEmpty(url)) {
				continue;
			}

			if (antPathMatcher.match(url, requestUrl)) {
				return uacAction;
			}

		}
		return null;
	}

	@Override
	public boolean checkActionCode(UacActionCheckCodeDto uacActionCheckCodeDto) {
		Long id = uacActionCheckCodeDto.getActionId();
		String actionCode = uacActionCheckCodeDto.getActionCode();

		Example example = new Example(UacAction.class);
		Example.Criteria criteria = example.createCriteria();

		if (id != null) {
			criteria.andNotEqualTo("id", id);
		}
		criteria.andEqualTo("actionCode", actionCode);

		int result = selectCountByExample(example);

		return result < 1;
	}

	/**
	 * 校验功能URL是否唯一
	 *
	 * @param uacActionCheckUrlDto the uac action check url dto
	 *
	 * @return the boolean, true-不存在, false-已存在
	 */
	@Override
	public boolean checkActionUrl(UacActionCheckUrlDto uacActionCheckUrlDto) {

		Long id = uacActionCheckUrlDto.getActionId();
		String url = uacActionCheckUrlDto.getUrl();

		Example example = new Example(UacAction.class);
		Example.Criteria criteria = example.createCriteria();

		if (id != null) {
			criteria.andNotEqualTo("id", id);
		}
		criteria.andEqualTo("url", url);

		int result = selectCountByExample(example);

		return result < 1;
	}

    /**
     * 修改功能信息
     *
     * @param action       the uac action
     * @param loginAuthDto the login auth dto
     *
     * @return the int.
     */
    @Override
    public Integer editUacAction(UacAction action, LoginAuthDto loginAuthDto) {

        // 校验Id是否为空
        Preconditions.checkArgument(action.getId() != null,
                cmnyMessageSource.getMessage("action.id.null", null));

        // 校验功能是否存在
        UacAction uacAction = selectByKey(action.getId());
        if (PublicUtil.isEmpty(uacAction)) {
            throw new UacBizException(ErrorCodeEnum.UAC10014004);
        }

        if (PublicUtil.isNotEmpty(action.getActionCode())
                && !action.getActionCode().equals(uacAction.getActionCode())) {
            // 校验功能编码是否唯一
            UacActionCheckCodeDto uacActionCheckCodeDto = new UacActionCheckCodeDto();
            uacActionCheckCodeDto.setActionId(action.getId());
            uacActionCheckCodeDto.setActionCode(action.getActionCode());
            Preconditions.checkArgument(checkActionCode(uacActionCheckCodeDto),
                    cmnyMessageSource.getMessage("action.code.exist", null));
        }

        if (PublicUtil.isNotEmpty(action.getUrl())
                && !action.getUrl().equals(uacAction.getUrl())) {
            // 校验功能url是否唯一
            UacActionCheckUrlDto uacActionCheckUrlDto = new UacActionCheckUrlDto();
            uacActionCheckUrlDto.setUrl(action.getUrl());
            uacActionCheckUrlDto.setActionId(action.getId());
            Preconditions.checkArgument(checkActionUrl(uacActionCheckUrlDto),
                    cmnyMessageSource.getMessage("action.url.exist", null));
        }

        if (PublicUtil.isNotEmpty(action.getMenuId())
            && !action.getMenuId().equals(uacAction.getMenuId())) {
            // 校验菜单是否存在
            UacMenu uacMenu = uacMenuService.selectByKey(action.getMenuId());
            if (PublicUtil.isEmpty(uacMenu)) {
                throw new UacBizException(ErrorCodeEnum.UAC10013003);
            }
        }

        return uacActionMapper.updateByPrimaryKeySelective(action);
    }

	/**
	 * 查询功能列表
	 *
	 * @param actionMainQueryDto the action main query dto
	 *
	 * @return the list
	 */
	@Override
	public List<UacAction> queryActionList(ActionMainQueryDto actionMainQueryDto) {

		return uacActionMapper.queryActionList(actionMainQueryDto);
	}

	/**
	 * 查询角色功能列表
	 *
	 * @param actionMainQueryDto the action main query dto
	 *
	 * @return the list
	 */
	@Override
	public List<UacAction> queryRoleActionList(ActionMainQueryDto actionMainQueryDto) {

		return uacActionMapper.queryRoleActionList(actionMainQueryDto);
	}
}
